package com.hyt.it.ogt.ykcj.service.grade.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hyt.core.base.BaseEntity;
import com.hyt.core.constant.CommonConstant;
import com.hyt.it.ogt.ykcj.common.constant.HttpStatus;
import com.hyt.it.ogt.ykcj.common.enums.CommonEnums;
import com.hyt.it.ogt.ykcj.common.enums.ExamFormEnums;
import com.hyt.it.ogt.ykcj.common.enums.PublishTypeEnums;
import com.hyt.it.ogt.ykcj.common.enums.ShowTypeEnums;
import com.hyt.it.ogt.ykcj.common.enums.zs.CertificateStatusEnums;
import com.hyt.it.ogt.ykcj.common.exception.CustomException;
import com.hyt.it.ogt.ykcj.common.utils.DateUtils;
import com.hyt.it.ogt.ykcj.domain.exam.ExamInfo;
import com.hyt.it.ogt.ykcj.domain.exam.ExamNameConfig;
import com.hyt.it.ogt.ykcj.domain.exam.ExamPublishCertificateInfo;
import com.hyt.it.ogt.ykcj.domain.grade.*;
import com.hyt.it.ogt.ykcj.domain.vo.*;
import com.hyt.it.ogt.ykcj.domain.zs.ZsExamineeInfo;
import com.hyt.it.ogt.ykcj.domain.zs.ZsInfo;
import com.hyt.it.ogt.ykcj.domain.zs.dto.ZsExamineeInfoExportZip;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamNameConfigMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamSubjectInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.grade.*;
import com.hyt.it.ogt.ykcj.service.exam.IExamPublishCertificateInfoService;
import com.hyt.it.ogt.ykcj.service.grade.IEnterpriseExamineeCertificateRelationService;
import com.hyt.it.ogt.ykcj.service.grade.IScoreQueryService;
import com.hyt.it.ogt.ykcj.service.zs.IZsExamineeInfoService;
import com.hyt.it.ogt.ykcj.service.zs.IZsInfoService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 企业招聘考生成绩查询Service业务层处理
 *
 * @author liying
 * @date 2021-11-19
 */
@Service

public class ScoreQueryServiceImpl implements IScoreQueryService {
    private static final Logger log = LoggerFactory.getLogger(ScoreQueryServiceImpl.class);

    @Autowired
    private EnterpriseExamineeInfoMapper enterpriseExamineeInfoMapper;

    @Autowired
    private ExamInfoMapper examInfoMapper;

    @Autowired
    private ExamNameConfigMapper examNameConfigMapper;

    @Autowired
    private EnterpriseExamineeSubjectGradeMapper enterpriseExamineeSubjectGradeMapper;

    @Autowired
    private ExamSubjectInfoMapper eamSubjectInfoMapper;

    @Autowired
    private ExamPublishInfoMapper examPublishInfoMapper;

    @Autowired
    private ExamPublishSubjectInfoMapper examPublishSubjectInfoMapper;

    @Autowired
    private ExamReviewInfoMapper examReviewInfoMapper;

    @Autowired
    private IZsExamineeInfoService zsExamineeInfoService;
    @Resource
    IExamPublishCertificateInfoService examPublishCertificateInfoService;
    @Resource
    IEnterpriseExamineeCertificateRelationService enterpriseExamineeCertificateRelationService;
    @Resource
    IZsInfoService zsInfoService;

    @Override
    public Map<Integer, String> verificationInformation(String examId, String examineeName, String admissionnNo) {
        Map<Integer, String> retMap = new HashMap<>(1);
        //考试组

        List<ExamInfoVo> examInfoVos = getExamInfoVos(examId);
        List<String> examIds = new ArrayList<>(4);
        if (CollectionUtils.isNotEmpty(examInfoVos)) {
            examIds = examInfoVos.stream().map(e -> e.getId()).collect(Collectors.toList());
        } else {
            ExamInfo examInfo = examInfoMapper.selectExamInfoById(examId);
            if (null == examInfo) {
                retMap.put(HttpStatus.ERROR, "成绩尚未发布，请耐心等待！");
                return retMap;
            }
            examIds.add(examInfo.getId());
        }
        List<EnterpriseExamineeInfo> enterpriseExamineeInfos = new ArrayList<>(examIds.size());
        if (examIds.size() > 1) {
            for (String tempExamId : examIds)
                enterpriseExamineeInfos.addAll(enterpriseExamineeInfoMapper.selectExamineeInfoByCertificatesAndExaminId(tempExamId, examineeName, admissionnNo));

        } else {
            enterpriseExamineeInfos.addAll(enterpriseExamineeInfoMapper.selectExamineeInfoByCertificatesAndExaminId(examId, examineeName, admissionnNo));

        }
        if (CollectionUtils.isEmpty(enterpriseExamineeInfos)) {
            retMap.put(HttpStatus.ERROR, "未查询到考生信息！");
            return retMap;
        }

        Map<String, EnterpriseExamineeInfo> examineeInfoMap = enterpriseExamineeInfos.stream().collect(Collectors.toMap(EnterpriseExamineeInfo::getName, examineeInfo -> examineeInfo, (key1, key2) -> key2));

        if (null == examineeInfoMap.get(examineeName)) {
            retMap.put(HttpStatus.ERROR, "未查询到考生信息！");
            return retMap;
        }

        if (CommonEnums.ARCHIVED_STATUS_N.getCode().equals(examineeInfoMap.get(examineeName).getArchivedStatus())) {
            retMap.put(HttpStatus.ERROR, "成绩尚未发布，请耐心等待！");
            return retMap;
        }
        LambdaQueryWrapper<ExamPublishInfo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ExamPublishInfo::getExamId, examId);
        List<ExamPublishInfo> examPublishInfos = examPublishInfoMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(examPublishInfos)) {
            retMap.put(HttpStatus.ERROR, "成绩尚未发布，请耐心等待！");
            return retMap;
        }

        Map<Integer, ExamPublishInfo> examPublishInfoMap = examPublishInfos.stream().collect(Collectors.toMap(ExamPublishInfo::getPublishType, examSubjectInfo -> examSubjectInfo, (key1, key2) -> key2));
//        if(null != examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_2.getCode())){
//            String msg = checkValidDate(examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_2.getCode()));
//            if(StringUtils.isNotEmpty(msg)){
//                retMap.put(HttpStatus.ERROR,msg);
//                return retMap;
//            }
//         }
//        if(null != examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_1.getCode())){
//            String msg = checkValidDate(examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_1.getCode()));
//            if(StringUtils.isNotEmpty(msg)){
//                retMap.put(HttpStatus.ERROR,msg);
//                return retMap;
//            }
//         }
        if (null != examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_0.getCode())) {
            String msg = checkValidDate(examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_0.getCode()));
            if (StringUtils.isNotEmpty(msg)) {
                retMap.put(HttpStatus.ERROR, msg);
                return retMap;
            }
        }
        retMap.put(HttpStatus.SUCCESS, examineeInfoMap.get(examineeName).getId());
        return retMap;
    }

    @Override
    public QueryExamExamineeDetailVo queryExamExamineeResultDetail(String examineeId, String examId) {
        EnterpriseExamineeInfo enterpriseExamineeInfo = enterpriseExamineeInfoMapper.selectEnterpriseExamineeInfoById(examineeId);
        if (null == enterpriseExamineeInfo) {
            return null;
        }
        ExamInfo examInfo = examInfoMapper.selectExamInfoById(examId);
        if (null == examInfo) {
            return null;
        }
        ExamNameConfig examNameConfig = examNameConfigMapper.selectExamNameConfigById(examInfo.getExamNameConfigId());

        LambdaQueryWrapper<ExamPublishInfo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ExamPublishInfo::getExamId, examInfo.getId());
        List<ExamPublishInfo> examPublishInfos = examPublishInfoMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(examPublishInfos)) {
            return null;
        }
        // Map<PublishType, ExamPublishInfo>
        Map<Integer, ExamPublishInfo> examPublishInfoMap = examPublishInfos.stream()
                .collect(Collectors.toMap(ExamPublishInfo::getPublishType,
                        examSubjectInfo -> examSubjectInfo,
                        (key1, key2) -> key2));
        QueryExamExamineeDetailVo queryExamExamineeDetailVo = new QueryExamExamineeDetailVo();
        queryExamExamineeDetailVo.setAdmissionNo(enterpriseExamineeInfo.getAdmissionNo());
        queryExamExamineeDetailVo.setIdcard(enterpriseExamineeInfo.getIdcard());
        queryExamExamineeDetailVo.setExamDayEndTime(examInfo.getExamEndDay());
        queryExamExamineeDetailVo.setExamDayStartTime(examInfo.getExamStartDay());
        queryExamExamineeDetailVo.setExamineeId(enterpriseExamineeInfo.getId());
        queryExamExamineeDetailVo.setMobile(enterpriseExamineeInfo.getMobile());
        queryExamExamineeDetailVo.setExamId(examInfo.getId());
        queryExamExamineeDetailVo.setExamForm(examInfo.getExamForm());
        if (null != examNameConfig) {
            queryExamExamineeDetailVo.setExamName(examNameConfig.getName());
        }
        queryExamExamineeDetailVo.setName(enterpriseExamineeInfo.getName());
        if (null != examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_2.getCode()) &&
                Integer.valueOf(CommonEnums.CHECK_STATUS_1.getCode()).equals(examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_2.getCode()).getShowPublishTypeResult())) {
            //默认取考生表中复核状态
            queryExamExamineeDetailVo.setReviewStatus(enterpriseExamineeInfo.getReviewStatus());
            LambdaQueryWrapper<ExamReviewInfo> examReviewWrapper = Wrappers.lambdaQuery();
            examReviewWrapper.eq(ExamReviewInfo::getExamId, examInfo.getId())
                    .eq(ExamReviewInfo::getExamineeId, enterpriseExamineeInfo.getId());
            //已经申请则显示查看
            List<ExamReviewInfo> examReviewInfos = examReviewInfoMapper.selectList(examReviewWrapper);
            if (CollectionUtils.isNotEmpty(examReviewInfos)) {
                queryExamExamineeDetailVo.setReviewId(examReviewInfos.get(0).getId());
                queryExamExamineeDetailVo.setReviewStatus(Integer.valueOf(CommonEnums.REVIEW_STATUS_1.getCode()));
            } else {
                //不在有效期内，不显示
                if (StringUtils.isNotEmpty(checkValidDate(examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_2.getCode())))) {
                    queryExamExamineeDetailVo.setReviewStatus(null);
                }
            }
        }
        if (null != examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_1.getCode())
                && Integer.valueOf(CommonEnums.CHECK_STATUS_1.getCode()).equals(examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_1.getCode()).getShowPublishTypeResult())) {
            //允许查看试卷
            queryExamExamineeDetailVo.setQueryPaper(PublishTypeEnums.PUBLISH_TYPE_1.getCode());
            //不在查看时间段内，不让查看试卷
            if (StringUtils.isNotEmpty(checkValidDate(examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_1.getCode())))) {
                queryExamExamineeDetailVo.setQueryPaper(0);
            }
        }

        if (null != examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_0.getCode()) &&
                Integer.valueOf(CommonEnums.CHECK_STATUS_1.getCode()).equals(examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_0.getCode()).getShowPublishTypeResult())) {
            ExamPublishInfo examPublishInfo = examPublishInfoMap.get(PublishTypeEnums.PUBLISH_TYPE_0.getCode());
            if (StringUtils.isEmpty(examPublishInfo.getShowType())) {
                return queryExamExamineeDetailVo;
            }
            List<String> showTypes = Arrays.asList(examPublishInfo.getShowType().split(","));
            Map<String, ExamPublishInfo> examShowTypeMap = new HashMap<>(showTypes.size());
            for (String type : showTypes) {
                ExamPublishInfo examPublish = new ExamPublishInfo();
                BeanUtils.copyProperties(examPublishInfo, examPublish);
                examPublish.setShowType(type);
                examShowTypeMap.put(type, examPublish);
            }
            List<ExamineeSubjectScoreVo> scoreList = null;
            List<ExamineeExamScoreVo> examScoreList = null;
            if (null != examShowTypeMap.get(ShowTypeEnums.SHOW_TYPE_5.getCode())) {
                examScoreList = buildExamineeExamScoreVos(enterpriseExamineeInfo, examInfo.getId());
                //显示考试总成绩
                if (CollectionUtils.isNotEmpty(examScoreList) && null != examShowTypeMap.get(ShowTypeEnums.SHOW_TYPE_0.getCode())) {
                    queryExamExamineeDetailVo.setScore(examScoreList.stream().filter(s -> null != s.getScore()).map(ExamineeExamScoreVo::getScore).reduce(BigDecimal.ZERO, BigDecimal::add));
                    queryExamExamineeDetailVo.setResultScore(examScoreList.stream().filter(s -> null != s.getResultScore()).map(ExamineeExamScoreVo::getResultScore).reduce(BigDecimal.ZERO, BigDecimal::add));
                }
            } else {
                scoreList = buildExamineeSubjectScoreVos(examInfo.getId(), queryExamExamineeDetailVo.getExamineeId());
                //显示考试总成绩
                if (CollectionUtils.isNotEmpty(scoreList) && null != examShowTypeMap.get(ShowTypeEnums.SHOW_TYPE_0.getCode())) {
                    queryExamExamineeDetailVo.setScore(scoreList.stream().filter(s -> null != s.getScore()).map(ExamineeSubjectScoreVo::getScore).reduce(BigDecimal.ZERO, BigDecimal::add));
                    queryExamExamineeDetailVo.setResultScore(scoreList.stream().filter(s -> null != s.getResultScore()).map(ExamineeSubjectScoreVo::getResultScore).reduce(BigDecimal.ZERO, BigDecimal::add));
                }
            }

            //显示考试结果
            if (null != examShowTypeMap.get(ShowTypeEnums.SHOW_TYPE_1.getCode())) {
                if (StringUtils.isNotEmpty(enterpriseExamineeInfo.getRegionName())) {
                    queryExamExamineeDetailVo.setQualifiedStatus(enterpriseExamineeInfo.getRegionName());
                } else if (StringUtils.isNotEmpty(enterpriseExamineeInfo.getQualifiedStatus())) {
                    queryExamExamineeDetailVo.setQualifiedStatus(enterpriseExamineeInfo.getQualifiedStatus());
                } else {
                    queryExamExamineeDetailVo.setQualifiedStatus(null);
                }
            }

            if (null != examShowTypeMap.get(ShowTypeEnums.SHOW_TYPE_5.getCode())) {
                if (StringUtils.isNotEmpty(enterpriseExamineeInfo.getGroupRegionName())) {
                    queryExamExamineeDetailVo.setQualifiedStatus(enterpriseExamineeInfo.getGroupRegionName());
                } else if (StringUtils.isNotEmpty(enterpriseExamineeInfo.getGroupQualifiedStatus())) {
                    queryExamExamineeDetailVo.setQualifiedStatus(enterpriseExamineeInfo.getGroupQualifiedStatus());
                } else {
                    queryExamExamineeDetailVo.setQualifiedStatus(null);
                }
            }
            //普通考试
            //显示科目信息
            if (CollectionUtils.isNotEmpty(scoreList) && null != examShowTypeMap.get(ShowTypeEnums.SHOW_TYPE_2.getCode())) {
                LambdaQueryWrapper<ExamPublishSubjectInfo> gradeWrapper = Wrappers.lambdaQuery();
                gradeWrapper.eq(ExamPublishSubjectInfo::getExamPublishId, examShowTypeMap.get(ShowTypeEnums.SHOW_TYPE_2.getCode()).getId());
                //发布成绩的选项
                List<ExamPublishSubjectInfo> examPublishSubjectInfos = examPublishSubjectInfoMapper.selectList(gradeWrapper);
                Map<String, ExamineeSubjectScoreVo> scoreMap = scoreList.stream().collect(Collectors.toMap(ExamineeSubjectScoreVo::getSubjectId, ExamineeSubjectScoreVo -> ExamineeSubjectScoreVo, (key1, key2) -> key2));
                for (ExamPublishSubjectInfo publishSubjectInfo : examPublishSubjectInfos) {
                    ExamineeSubjectScoreVo subjectScoreVo = scoreMap.get(publishSubjectInfo.getSubjectId());
                    if (null == subjectScoreVo) {
                        continue;
                    }
                    //未选择设置值为null
                    if (Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(publishSubjectInfo.getShowSubjectScore())) {
                        subjectScoreVo.setResultScore(null);
                        subjectScoreVo.setScore(null);
                    }
                    if (Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(publishSubjectInfo.getShowSubjectResult())) {
                        subjectScoreVo.setQualifiedStatus(null);
                    }
                    //过滤未选择发布的科目
                    if (Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(publishSubjectInfo.getShowSubjectResult())
                            && Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(publishSubjectInfo.getShowSubjectScore())) {
                        scoreList.remove(subjectScoreVo);
                    }

                }
                queryExamExamineeDetailVo.setScoreList(scoreList);
                //自选科目发布就是普通考试
                queryExamExamineeDetailVo.setExamForm(ExamFormEnums.FORM_EXAM.getCode());
            }
            //考试组
            if (CollectionUtils.isNotEmpty(examScoreList) && null != examShowTypeMap.get(ShowTypeEnums.SHOW_TYPE_5.getCode())) {
                LambdaQueryWrapper<ExamPublishSubjectInfo> gradeWrapper = Wrappers.lambdaQuery();
                gradeWrapper.eq(ExamPublishSubjectInfo::getExamPublishId, examShowTypeMap.get(ShowTypeEnums.SHOW_TYPE_5.getCode()).getId());
                //发布考试的选项
                List<ExamPublishSubjectInfo> examPublishSubjectInfos = examPublishSubjectInfoMapper.selectList(gradeWrapper);
                //按考试分组
                Map<String, List<ExamPublishSubjectInfo>> examPublishMap = examPublishSubjectInfos.stream().collect(Collectors.groupingBy(c -> c.getRelationExamId()));
                Map<String, ExamineeExamScoreVo> scoreMap = examScoreList.stream().collect(Collectors.toMap(ExamineeExamScoreVo::getExamId, ExamineeExamScoreVo -> ExamineeExamScoreVo, (key1, key2) -> key2));

                for (String key : examPublishMap.keySet()) {
                    ExamineeExamScoreVo examScoreVo = scoreMap.get(key);
                    if (null == examScoreVo) {
                        continue;
                    }
                    //未选择设置值为null
                    if (Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(examPublishMap.get(key).get(0).getShowSubjectScore())) {
                        examScoreVo.setResultScore(null);
                        examScoreVo.setScore(null);
                    }
                    if (Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(examPublishMap.get(key).get(0).getShowSubjectResult())) {
                        examScoreVo.setQualifiedStatus(null);
                    }
                    //过滤未选择发布的考试
                    if (Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(examPublishMap.get(key).get(0).getShowSubjectResult())
                            && Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(examPublishMap.get(key).get(0).getShowSubjectScore())) {
                        examScoreList.remove(examScoreVo);
                    }
                    for (ExamPublishSubjectInfo publishSubjectInfo : examPublishMap.get(key)) {
                        //未选择设置值为null
                        if (Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(publishSubjectInfo.getShowSubjectScore())) {
                            examScoreVo.setResultScore(null);
                            examScoreVo.setScore(null);
                        }
                        if (Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(publishSubjectInfo.getShowSubjectResult())) {
                            examScoreVo.setQualifiedStatus(null);
                        }
                        //过滤未选择发布的科目
                        if (Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(publishSubjectInfo.getShowSubjectResult())
                                && Integer.valueOf(CommonEnums.CHECK_STATUS_0.getCode()).equals(publishSubjectInfo.getShowSubjectScore())) {
                            examScoreList.remove(examScoreVo);
                        }
                    }

                }
                queryExamExamineeDetailVo.setExamScoreList(examScoreList);
            }
        }

        // 证书下载
        ExamPublishInfo zsExamPublishInfo = examPublishInfoMap.get(PublishTypeEnums.ZS_DOWNLOAD_TYPE_3.getCode());
        if (null != zsExamPublishInfo) {
            // 证书下载发布显示
            if (NumberUtil.equals(zsExamPublishInfo.getShowPublishTypeResult(), CommonConstant.ONE)) {
                List<ExamPublishCertificateInfo> examPublishCertificateInfos = examPublishCertificateInfoService.listByExamId(examId);
                // Map<ZsInfoId, ExamPublishCertificateInfo>
                Map<String, ExamPublishCertificateInfo> certificateInfoMap = examPublishCertificateInfos.stream()
                        .collect(Collectors.toMap(ExamPublishCertificateInfo::getZsInfoId, data -> data, (before, after) -> before));
                // 考试绑定的证书
                List<ZsInfo> zsInfoList = examPublishCertificateInfos.stream()
                        .map(ExamPublishCertificateInfo::getZsInfoId)
                        .distinct()
                        .map(zsInfoService::selectCacheById)
                        // 证书要为发布状态
                        .filter(zsInfo -> NumberUtil.equals(zsInfo.getCertificateStatus(), CertificateStatusEnums.PUBLISHED.getCode()))
                        // 证书不能被删除掉
                        .filter(zsInfo -> BooleanUtil.isFalse(zsInfo.getDelFlag()))
                        .collect(Collectors.toList());
                if (log.isDebugEnabled()) {
                    log.debug("#查询到考生可以查询到的证书为：{}", JSONUtil.toJsonStr(zsInfoList));
                }
                if (CollUtil.isNotEmpty(zsInfoList)) {
                    // Map<ZsInfoId, CertificateName>
                    Map<String, String> zsInfoIdMappingCertificateName = zsInfoList.stream()
                            .collect(Collectors.toMap(BaseEntity::getId, ZsInfo::getCertificateName, (before, after) -> before));
                    // 获取证书ID
                    List<String> zsInfoIds = zsInfoList.stream()
                            .map(BaseEntity::getId)
                            .collect(Collectors.toList());
                    // 获取考生获得的证书关系
                    List<String> zsExamineeIds = enterpriseExamineeCertificateRelationService.listCanViewByExaminee(examId, examineeId, zsInfoIds);
                    if (CollUtil.isNotEmpty(zsExamineeIds)) {
                        // 获取考生已发放的可以查询到的证书
                        List<ZsExamineeInfo> examineeInfos = zsExamineeInfoService.listByCanViewByIds(zsExamineeIds);
                        List<ExamineeCertificateViewVO> examineeCertificateViewVOS = examineeInfos.stream()
                                .map(data -> BeanUtil.toBean(data, ExamineeCertificateViewVO.class))
                                .peek(data -> {
                                    // 设置证书名称
                                    String certificateName = MapUtil.getStr(zsInfoIdMappingCertificateName, data.getZsId());
                                    data.setCertificateName(certificateName);

                                    // 考生证书发布查询字段显示控制
                                    ExamPublishCertificateInfo examPublishCertificateInfo = MapUtil.get(certificateInfoMap, data.getZsId(), ExamPublishCertificateInfo.class);
                                    // 证书名称
                                    if (NumberUtil.equals(examPublishCertificateInfo.getShowCertificate(), CommonConstant.ZERO)) {
                                        data.setCertificateName(null);
                                    }
                                    // 专业
                                    if (NumberUtil.equals(examPublishCertificateInfo.getShowSpeciality(), CommonConstant.ZERO)) {
                                        data.setCertificateSubjectName(null);
                                    }
                                    // 级别
                                    if (NumberUtil.equals(examPublishCertificateInfo.getShowLevel(), CommonConstant.ZERO)) {
                                        data.setCertificateLevelDesc(null);
                                    }

                                })
                                .collect(Collectors.toList());
                        queryExamExamineeDetailVo.setExamineeCertificateView(examineeCertificateViewVOS);
                    } else {
                        log.debug("#当前考生[{}]考试[{}]成绩未查询到获得的证书", examineeId, examId);
                    }
                } else {
                    log.debug("#当前考生[{}]考试[{}]成绩未查询到绑定的有效证书", examineeId, examId);
                }
            } else {
                log.debug("#当前考生[{}]考试[{}]成绩未开启证书显示", examineeId, examId);
            }
        } else {
            log.debug("#当前考生[{}]考试[{}]成绩查询未设置证书配置", examineeId, examId);
        }
        return queryExamExamineeDetailVo;
    }

    @Override
    public String batchExportCertificateZip(String examineeId, String examId) {
        EnterpriseExamineeInfo enterpriseExamineeInfo = enterpriseExamineeInfoMapper.selectEnterpriseExamineeInfoById(examineeId);
        if (null == enterpriseExamineeInfo) {
            throw new CustomException("未查询到考生信息");
        }
        ExamInfo examInfo = examInfoMapper.selectExamInfoById(examId);
        if (null == examInfo) {
            throw new CustomException("未查询到考试信息");
        }
        List<ExamPublishCertificateInfo> examPublishCertificateInfos = examPublishCertificateInfoService.listByExamId(examId);
        // 考试绑定的证书
        List<ZsInfo> zsInfoList = examPublishCertificateInfos.stream()
                .map(ExamPublishCertificateInfo::getZsInfoId)
                .distinct()
                .map(zsInfoService::selectCacheById)
                // 证书要为发布状态
                .filter(zsInfo -> NumberUtil.equals(zsInfo.getCertificateStatus(), CertificateStatusEnums.PUBLISHED.getCode()))
                // 证书不能被删除掉
                .filter(zsInfo -> BooleanUtil.isFalse(zsInfo.getDelFlag()))
                .collect(Collectors.toList());
        if (log.isDebugEnabled()) {
            log.debug("#查询到考生可以查询到的证书为：{}", JSONUtil.toJsonStr(zsInfoList));
        }
        if (CollUtil.isEmpty(zsInfoList)) {
            throw new CustomException("未查询到绑定的有效证书");
        }
        // 获取证书ID
        List<String> zsInfoIds = zsInfoList.stream()
                .map(BaseEntity::getId)
                .collect(Collectors.toList());
        // 获取考生获得的证书关系
        List<String> zsExamineeIds = enterpriseExamineeCertificateRelationService.listCanViewByExaminee(examId, examineeId, zsInfoIds);
        if (CollUtil.isEmpty(zsExamineeIds)) {
            throw new CustomException("未查询到获得的证书");
        }
        // 获取考生已发放的可以查询到的证书
        List<ZsExamineeInfo> examineeInfos = zsExamineeInfoService.listByCanViewByIds(zsExamineeIds);
        if (CollUtil.isEmpty(examineeInfos)) {
            throw new CustomException("未查询到可导出的证书");
        }
        ExamNameConfig examNameConfig = examNameConfigMapper.selectExamNameConfigById(examInfo.getExamNameConfigId());
        String examName = Optional.ofNullable(examNameConfig)
                .map(ExamNameConfig::getName)
                .filter(StrUtil::isNotBlank)
                .orElseGet(examInfo::getId);

        String lastFileName = StrUtil.format("{}_{}_{}.zip", examName, enterpriseExamineeInfo.getName(), System.currentTimeMillis());
        String exportedCertificateHasSignaturePdfZipUrl = exportCertificatePdfZip(lastFileName, examineeInfos, zsInfoList);
        return exportedCertificateHasSignaturePdfZipUrl;
    }

    /**
     * 导出带有电子签章的ZIP文件
     *
     * @param fileName
     * @param examineesInfos
     * @return
     */
    private String exportCertificatePdfZip(String fileName, List<ZsExamineeInfo> examineesInfos, List<ZsInfo> zsInfoList) {
        // Map<zsInfoId, CertificateName>
        Map<String, String> certificateInfoNaming = zsInfoList.stream()
                .collect(Collectors.toMap(BaseEntity::getId, ZsInfo::getCertificateName));

        List<ZsExamineeInfoExportZip> examineeInfoExportZips = examineesInfos.stream()
                .map(data -> {
                    String certificateName = MapUtil.getStr(certificateInfoNaming, data.getZsId());

                    ZsExamineeInfoExportZip examineeInfoExportZip = BeanUtil.toBean(data, ZsExamineeInfoExportZip.class);
                    examineeInfoExportZip.setExamineeName(certificateName);
                    examineeInfoExportZip.setUrl(data.getCertificatePdfUrl());
                    return examineeInfoExportZip;
                })
                .collect(Collectors.toList());
        return zsInfoService.exportCertificatePdfZip(fileName, examineeInfoExportZips);
    }

    private String checkValidDate(ExamPublishInfo examPublish) {
        if (Integer.valueOf(CommonEnums.SEE_TYPE_1.getCode()).equals(examPublish.getSeeType())) {
            if (DateUtils.getNowDate().before(examPublish.getStartDay()) || DateUtils.getNowDate().after(examPublish.getEndDay())) {
                return "成绩查询不在有效期间内！";
            }
        }
        return null;
    }

    /**
     * 获取考生考试所考的科目信息
     *
     * @param examId
     * @param examineeId
     * @return
     */
    private List<ExamineeSubjectScoreVo> buildExamineeSubjectScoreVos(String examId, String examineeId) {
        //考试的所有科目
        List<ExamSubjectVo> examSubjectVos = eamSubjectInfoMapper.selectExamSubjectInfoByExamId(examId);
        if (CollectionUtils.isEmpty(examSubjectVos)) {
            return Collections.EMPTY_LIST;
        }
        List<ExamineeSubjectScoreVo> scoreList = new ArrayList<>(examSubjectVos.size());
        //考生考的科目
        List<EnterpriseExamineeSubjectGrade> enterpriseExamineeSubjectGrades = enterpriseExamineeSubjectGradeMapper.selectArchiveEnterpriseExamineeSubjectGradeList(new String[]{examineeId}, examId, null);
        Map<String, EnterpriseExamineeSubjectGrade> subjectScoreMap = enterpriseExamineeSubjectGrades.stream().collect(Collectors.toMap(EnterpriseExamineeSubjectGrade::getSubjectId, enterpriseExamineeSubjectGrade -> enterpriseExamineeSubjectGrade, (k1, k2) -> k2));

        for (ExamSubjectVo examSubjectVo : examSubjectVos) {
            if (MapUtils.isEmpty(subjectScoreMap) || null == subjectScoreMap.get(examSubjectVo.getSubjectId())
                    || !CommonEnums.ARCHIVED_STATUS_Y.getCode().equals(subjectScoreMap.get(examSubjectVo.getSubjectId()).getArchivedStatus())) {
                continue;
            }
            ExamineeSubjectScoreVo examineeSubjectScoreVo = new ExamineeSubjectScoreVo();
            examineeSubjectScoreVo.setSubjectId(examSubjectVo.getSubjectId());
            examineeSubjectScoreVo.setSubjectName(examSubjectVo.getSubjectName());
            examineeSubjectScoreVo.setScore(examSubjectVo.getPaperFullMarks());
            examineeSubjectScoreVo.setResultScore(subjectScoreMap.get(examSubjectVo.getSubjectId()).getScore());
            if (StringUtils.isNotEmpty(subjectScoreMap.get(examSubjectVo.getSubjectId()).getRegionName())) {
                examineeSubjectScoreVo.setQualifiedStatus(subjectScoreMap.get(examSubjectVo.getSubjectId()).getRegionName());
            } else {
                examineeSubjectScoreVo.setQualifiedStatus(subjectScoreMap.get(examSubjectVo.getSubjectId()).getQualifiedStatus());
            }
            scoreList.add(examineeSubjectScoreVo);
        }
        return scoreList;
    }


    /**
     * 获取考生考试所考的子考试信息
     *
     * @param examId
     * @return
     */
    private List<ExamineeExamScoreVo> buildExamineeExamScoreVos(EnterpriseExamineeInfo enterpriseExamineeInfo, String examId) {
        List<ExamInfoVo> examInfoVos = getExamInfoVos(examId);
        if (CollectionUtils.isEmpty(examInfoVos)) {
            return Collections.EMPTY_LIST;
        }
        List<String> examIds = examInfoVos.stream().distinct().map(e -> e.getId()).collect(Collectors.toList());
        Map<String, String> examNameMap = examInfoVos.stream().collect(Collectors.toMap(e -> e.getId(), e -> e.getExamNameConfigName(), (k1, k2) -> k2));
        //子考试考试的所有科目
        List<ExamSubjectVo> examSubjectVos = eamSubjectInfoMapper.selectExamSubjectInfoByExamIds(examIds.toArray(new String[examIds.size()]));
        if (CollectionUtils.isEmpty(examSubjectVos)) {
            return Collections.EMPTY_LIST;
        }

        List<ExamineeExamScoreVo> scoreList = new ArrayList<>(examSubjectVos.size());
        List<EnterpriseExamineeInfo> enterpriseExamineeInfos = new ArrayList<>();
        //考生考的科目
        List<EnterpriseExamineeSubjectGrade> enterpriseExamineeSubjectGrades = new ArrayList<>(10);
        if (CollectionUtils.isNotEmpty(examIds) && examIds.size() > 1) {
            QueryEnterpriseExamineeGradeVo queryExamineeGradeVo = new QueryEnterpriseExamineeGradeVo();
            queryExamineeGradeVo.setExamIds(examIds.toArray(new String[examIds.size()]));
            queryExamineeGradeVo.setIdcard(enterpriseExamineeInfo.getIdcard());
            queryExamineeGradeVo.setExamineeName(enterpriseExamineeInfo.getName());
            enterpriseExamineeInfos = enterpriseExamineeInfoMapper.selectExamineeExamList(queryExamineeGradeVo);
            List<String> examineeIds = enterpriseExamineeInfos.stream().distinct().map(e -> e.getId()).collect(Collectors.toList());
            enterpriseExamineeSubjectGrades.addAll(enterpriseExamineeSubjectGradeMapper.selectExamineeSubjectGradeListByExamineeIds(examineeIds.toArray(new String[examineeIds.size()]), examIds.toArray(new String[examIds.size()]), null));
        } else {
            enterpriseExamineeSubjectGrades.addAll(enterpriseExamineeSubjectGradeMapper.selectArchiveEnterpriseExamineeSubjectGradeList(new String[]{enterpriseExamineeInfo.getId()}, examId, null));
            enterpriseExamineeInfos.add(enterpriseExamineeInfo);
        }

        //按照考试分组
        Map<String, List<ExamSubjectVo>> examSubjectMap = examSubjectVos.stream().collect(Collectors.groupingBy(c -> c.getExamInfoId()));
        Map<String, List<EnterpriseExamineeSubjectGrade>> subjectScoreMap = enterpriseExamineeSubjectGrades.stream().collect(Collectors.groupingBy(c -> c.getExamId()));
        Map<String, EnterpriseExamineeSubjectGrade> examineeSubjectGradeMap = enterpriseExamineeSubjectGrades.stream().collect(Collectors.toMap(EnterpriseExamineeSubjectGrade::getSubjectId, enterpriseExamineeSubjectGrade -> enterpriseExamineeSubjectGrade, (k1, k2) -> k2));
        Map<String, EnterpriseExamineeInfo> enterpriseExamineeMap = enterpriseExamineeInfos.stream().collect(Collectors.toMap(EnterpriseExamineeInfo::getExamId, EnterpriseExamineeInfo -> EnterpriseExamineeInfo, (k1, k2) -> k2));
        for (String key : examSubjectMap.keySet()) {
            List<ExamSubjectVo> examVos = examSubjectMap.get(key);
            if (CollectionUtils.isEmpty(examVos)) {
                continue;
            }
            //过滤考生没有考的科目
            if (MapUtils.isEmpty(subjectScoreMap) || CollectionUtils.isEmpty(subjectScoreMap.get(key))) {
                continue;
            }
            List<ExamineeSubjectScoreVo> examineeSubjectScoreVos = new ArrayList<>(10);
            ExamineeExamScoreVo examineeExamScoreVo = new ExamineeExamScoreVo();
            examineeExamScoreVo.setExamId(examVos.get(0).getExamInfoId());
            examineeExamScoreVo.setExamName(examNameMap.get(examVos.get(0).getExamInfoId()));
            examineeExamScoreVo.setScore(examVos.stream().map(ExamSubjectVo::getPaperFullMarks).reduce(BigDecimal.ZERO, BigDecimal::add));


            List<EnterpriseExamineeSubjectGrade> examineeSubjectGrades = subjectScoreMap.get(key);
            examineeExamScoreVo.setResultScore(examineeSubjectGrades.stream().map(EnterpriseExamineeSubjectGrade::getScore).reduce(BigDecimal.ZERO, BigDecimal::add));
            if (null != enterpriseExamineeMap.get(key)) {
                examineeExamScoreVo.setQualifiedStatus(enterpriseExamineeMap.get(key).getQualifiedStatus());
                if (StringUtils.isNotEmpty(enterpriseExamineeMap.get(key).getRegionName())) {
                    examineeExamScoreVo.setQualifiedStatus(enterpriseExamineeMap.get(key).getRegionName());
                }
            } else {
                examineeExamScoreVo.setQualifiedStatus(enterpriseExamineeInfo.getQualifiedStatus());
            }

            for (ExamSubjectVo examSubjectVo : examVos) {
                if (null == examineeSubjectGradeMap.get(examSubjectVo.getSubjectId())) {
                    continue;
                }
                ExamineeSubjectScoreVo examineeSubjectScoreVo = new ExamineeSubjectScoreVo();
                examineeSubjectScoreVo.setSubjectId(examSubjectVo.getSubjectId());
                examineeSubjectScoreVo.setSubjectName(examSubjectVo.getSubjectName());
                examineeSubjectScoreVo.setScore(examSubjectVo.getPaperFullMarks());
                examineeSubjectScoreVo.setResultScore(examineeSubjectGradeMap.get(examSubjectVo.getSubjectId()).getScore());
                if (StringUtils.isNotEmpty(examineeSubjectGradeMap.get(examSubjectVo.getSubjectId()).getRegionName())) {
                    examineeSubjectScoreVo.setQualifiedStatus(examineeSubjectGradeMap.get(examSubjectVo.getSubjectId()).getRegionName());
                } else {
                    examineeSubjectScoreVo.setQualifiedStatus(examineeSubjectGradeMap.get(examSubjectVo.getSubjectId()).getQualifiedStatus());
                }
                examineeSubjectScoreVos.add(examineeSubjectScoreVo);
            }
            examineeExamScoreVo.setExamineeSubjectScoreVos(examineeSubjectScoreVos);
            scoreList.add(examineeExamScoreVo);

        }
        return scoreList;
    }

    private List<ExamInfoVo> getExamInfoVos(String examId) {
        List<ExamInfoVo> examInfoVos = null;
        ExamInfo examInfo = examInfoMapper.selectExamInfoById(examId);
        if (null != examInfo && null != examInfo.getMergeType() &&
                CommonEnums.EXAM_MERGE_TYPE_0.getCode().equals(String.valueOf(examInfo.getMergeType()))) {
            Map<String, Object> parms = new HashMap<>();
            parms.put("relationId", examId);
            examInfoVos = examInfoMapper.selectEnterpriseExamInfoByParms(parms);
        }

        return examInfoVos;
    }
}
